// 2013-7-28下午03:26:21  net.betou.trade.admin.action.IntermediateProviderRoleAct.java

package net.betou.trade.admin.action;

import static net.betou.common.page.SimplePage.cpn;
import static net.betou.common.page.SimplePage.cpnPageSize;

import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.betou.common.page.Pagination;
import net.betou.common.util.DataConvertUtils;
import net.betou.common.util.TradeUtils;
import net.betou.trade.action.abs.ActionSupport;
import net.betou.trade.entity.main.AgentAndAdmins;
import net.betou.trade.entity.main.Role;
import net.betou.trade.entity.main.RoleExt;
import net.betou.trade.main.manager.RoleExtMng;
import net.betou.trade.main.manager.agencyorproxy.AdminMng;
import net.betou.trade.main.manager.role.AgencyRoleMng;
import net.betou.trade.web.Messages;
import net.betou.trade.web.ResponseUtil;
import net.betou.trade.web.WebErrors;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 添加和更新的时候，角色列表将为动态的， 1. 如果是系统管理员，则分配出当前系统管理员指定的权限过去, 这是一个模板 2. 如果是其他的，则分配自己的
 * 
 * @author 叶装装
 */
@Controller
public class AgentRoleAct extends ActionSupport< Role >{

	private static final Logger log = LoggerFactory.getLogger( AgentRoleAct.class );

	private static final String DIRECTORY = "role/agent";

	@RequestMapping( "/agentrole/v_list.jspx" )
	public String v_list( Integer pageSize, Integer pageNo, String searchProperty, String searchValue, String orderProperty, String orderDirection, HttpServletRequest request, HttpServletResponse response, ModelMap model ) {

		pageSize = cpnPageSize( pageSize );
		pageNo = cpn( pageNo );

		AgentAndAdmins admin = TradeUtils.getAdmin( request );

		Pagination pagination = manager.getPage( admin, searchProperty, searchValue, orderProperty, orderDirection, pageSize, pageNo );

		paramToModel( model, pagination, null, pageSize, searchProperty, searchValue, orderProperty, orderDirection, null );
		model.addAttribute( "admin", admin );
		return getListPage( );

	}

	@RequestMapping( "/agentrole/v_add.jspx" )
	public String v_add( HttpServletRequest request, ModelMap model ) {
		AgentAndAdmins admin = TradeUtils.getAdmin( request );
		model.addAttribute( "admin", admin );
		return getAddPage( );
	}

	@RequestMapping( "/agentrole/o_save.jspx" )
	public String o_save( Role bean, String [ ] perms, ModelMap model, HttpServletRequest request ) {

		WebErrors errors = validateSave( bean, perms );

		if( errors.hasErrors( ) ){
			return errors.showErrorPage( model );
		}

		AgentAndAdmins admin = TradeUtils.getAdmin( request );

		bean = manager.save( admin, bean, splitPerms( perms ) );

		logMng.operating( 0, request, Messages.LOG_INTERMEDIA_ROLE, "id=" + bean.getId( ) + ",name=" + bean.getName( ) );

		return "redirect:v_list.jspx";
	}

	@RequestMapping( "/agentrole/v_edit.jspx" )
	public String v_edit( Integer id, String type, HttpServletRequest request, ModelMap model ) {
		WebErrors errors = validateUpdate( id );
		if( errors.hasErrors( ) ){
			return errors.showErrorPage( model );
		}

		AgentAndAdmins admin = TradeUtils.getAdmin( request );

		Role bean = manager.findById( id ); // 直接findById

		model.addAttribute( "bean", bean );
		model.addAttribute( "admin", admin );

		return getUpdatePage( );
	}

	@RequestMapping( "/agentrole/o_update.jspx" )
	public String o_update( Integer id, String [ ] perms, String name, Integer level, String description, HttpServletRequest request, ModelMap model ) {

		AgentAndAdmins admin = TradeUtils.getAdmin( request );

		WebErrors errors = validateOUpdate( admin, id );

		if( errors.hasErrors( ) ){
			return errors.showErrorPage( model );
		}

		Role bean = manager.findRole( admin, id );

		bean = manager.update( description, level, name, bean, this.splitPerms( perms ) );

		logMng.operating( 1, request, Messages.LOG_INTERMEDIA_ROLE, "id=" + bean.getId( ) + ",name=" + bean.getName( ) );

		return "redirect:v_list.jspx";

	}

	@RequestMapping( "/agentrole/o_delete.jspx" )
	public void delete( Integer [ ] ids, HttpServletRequest request, HttpServletResponse response ) {

		AgentAndAdmins admin = TradeUtils.getAdmin( request );

		ResponseUtil util = validateDelete( admin, ids, response );
		if( util.hasResponse( ) ){
			util.renderJson( );
			return;
		}

		Role [ ] beans = manager.deleteByIds( ids );

		for ( Role bean : beans ){
			log.info( "delete AgencyRole id={}", bean.getId( ) );
			logMng.operating( 2, request, Messages.LOG_INTERMEDIA_ROLE, "id=" + bean.getId( ) + ",name=" + bean.getName( ) );
		}

		util.addSuccessResponse( Messages.getDeleteSuccessMessage( beans.length ) );

		util.renderJson( );
		return;
	}

	/**
	 * 得出当前管理员，最高的查询权限，如当前管理员deep为0， 此时要得出属于这个管理员的最大deep
	 * 
	 * @param type
	 *            消息提示
	 * @return
	 */
	@RequestMapping( "/agentrole/v_setting_permission.jspx" )
	public String v_permission( String type, Integer id, Integer adminId, HttpServletRequest request, ModelMap model ) {

		AgentAndAdmins admin = TradeUtils.getAdmin( request );

		WebErrors errors = validateOUpdate( admin, id );

		if( errors.hasErrors( ) ){
			return errors.showErrorPage( model );
		}

		AgentAndAdmins editAdmin = null;

		Role bean = manager.findRole( admin, id );

		// 当系统管理员设置的时候，需要查询出对应的admin
		if( admin.getSystem( ) ){
			editAdmin = adminMng.findById( adminId ); // 要编辑的管理员
		}

		Set< RoleExt > roleExt = bean.getRoleExt( );

		if( roleExt == null || roleExt.isEmpty( ) ){
			roleExtMng.init( bean );
		}

		// 查找当前管理员最大deep.... 预留....

		// 可操作角色，选择条件，如果是系统管理员，则读取当前角色的所有角色(包括子角色)，如果非系统管理员，则按等级读取
		model.addAttribute( "roleList", manager.list( admin, editAdmin ) );
		model.addAttribute( "bean", bean );
		model.addAttribute( "admin", admin );

		if( "success".equals( type ) ){
			model.addAttribute( "message", Messages.DATA_EDIT_SUCCESS );
		}

		return DIRECTORY + "/permission";
	}

	@RequestMapping( "/agentrole/o_setting_permission.jspx" )
	public String o_permission( Integer id, HttpServletRequest request, ModelMap model ) {

		RoleExtContainer c = getRoleExtContainer( request );

		Collection< RoleExt > ec = c.getItems( );

		for ( RoleExt ext : ec ){
			roleExtMng.update( ext );
		}

		return "redirect:v_list.jspx";
	}

	@SuppressWarnings( "unchecked" )
	private RoleExtContainer getRoleExtContainer( HttpServletRequest request ) {
		Enumeration< String > e = request.getParameterNames( );

		RoleExtContainer container = new RoleExtContainer( );

		while( e.hasMoreElements( ) ){
			String param = e.nextElement( );

			if( !param.startsWith( "config" ) ){
				continue; // 如果不是配置的, 就继续循环
			}

			String [ ] split = StringUtils.split( param, "-" );

			if( split == null || split.length == 0 ){
				continue;
			}

			String field = split[ 1 ];
			Integer roleExtId = DataConvertUtils.getInt( split[ 2 ] );
			String value = getValues( request, param );

			String viewRoleConfig = split[ 0 ] + "-viewRole-" + roleExtId; // 得到可操作角色

			container.add( roleExtId, field, value, getValues( request, viewRoleConfig ) );
		}

		return container;
	}

	class RoleExtContainer{

		private Map< Integer, RoleExt > items;

		public RoleExtContainer( ) {
			items = new HashMap< Integer, RoleExt >( );
		}

		public Collection< RoleExt > getItems( ) {
			return items.values( );
		}

		public void add( Integer id, String param, String value, String viewRoles ) {
			param = StringUtils.deleteWhitespace( param );

			RoleExt ext = items.get( id );
			if( !items.containsKey( id ) ){
				ext = roleExtMng.findById( id );
				ext.setViewRoles( viewRoles ); // 只进行一次的设置
				items.put( id, ext );
			}

			if( !"viewRole".equals( param ) ){
				Integer intValue = DataConvertUtils.getInt( value );

				if( "findDeep".equals( param ) ){
					ext.setFindDeep( intValue );
				}

				// delete and update 不起作用,预留
				if( "deleteDeep".equals( param ) ){
					ext.setDeleteDeep( intValue );
				}

				if( "updateDeep".equals( param ) ){
					ext.setUpdateDeep( intValue );
				}
			}
		}
	}

	private String getValues( HttpServletRequest request, String param ) {
		String [ ] values = request.getParameterValues( param );

		if( values == null || values.length == 0 ){
			return null;
		}
		StringBuffer buffer = new StringBuffer( );
		for ( int i = 0; i < values.length; i++ ){
			buffer.append( values[ i ] );
			if( i < values.length - 1 ){
				buffer.append( "," );
			}
		}

		return buffer.toString( );
	}

	private ResponseUtil validateDelete( AgentAndAdmins admin, Integer [ ] ids, HttpServletResponse response ) {
		ResponseUtil util = ResponseUtil.create( response );

		if( ids == null || ids.length == 0 ){
			util.addErrorResponse( Messages.DATA_NOT_SELECT );
			return util;
		}
		for ( Integer id : ids ){
			Role role = manager.findRole( admin, id );
			boolean system = admin.getSystem( );

			if( role == null ){
				util.addErrorResponse( system ? Messages.DATA_NOT_EXIST : Messages.DATA_NOT_OPERATING );
				break;
			}
		}
		return util;
	}

	private WebErrors validateOUpdate( AgentAndAdmins admin, Integer id ) {
		WebErrors errors = WebErrors.create( );

		if( id == null || id == 0 ){
			errors.addError( Messages.DATA_NOT_EXIST );
			return errors;
		}

		Role bean = manager.findRole( admin, id );

		boolean system = admin.getSystem( );

		if( bean == null ){
			errors.addError( system ? Messages.DATA_NOT_EXIST : Messages.DATA_NOT_OPERATING );
			return errors;
		}

		return errors;
	}

	private WebErrors validateUpdate( Integer id ) {

		WebErrors errors = WebErrors.create( );

		if( id == null || id == 0 ){
			errors.addError( Messages.DATA_NOT_EXIST );
			return errors;
		}

		Role bean = manager.findById( id );

		if( bean == null ){
			errors.addError( Messages.DATA_NOT_EXIST );
			return errors;
		}

		return errors;
	}

	private WebErrors validateSave( Role bean, String [ ] perms ) {

		WebErrors errors = WebErrors.create( );
		String name = bean.getName( );

		if( errors.ifOutOfLength( name, "角色名称", 1, 100 ) ){
			return errors;
		}

		if( perms == null || perms.length == 0 ){
			errors.addError( Messages.ROLE_MESSAGE_NOT_CHOOSE_PERMISSION );
		}

		return errors;
	}

	@Autowired
	private RoleExtMng roleExtMng;

	// @Autowired
	// private AgentAndAdminsMng adminMng;

	@Autowired
	private AdminMng adminMng;

	@Autowired
	private AgencyRoleMng manager;

	@Override
	protected String getDirectory( ) {
		return DIRECTORY;
	}
}
